package com.yowasa.xiuxian.service.helper;

import com.yowasa.xiuxian.engine.battle.strategy.BattleStrategy;
import com.yowasa.xiuxian.engine.battle.strategy.BattleStrategyEngine;
import com.yowasa.xiuxian.engine.battle.strategy.DefendStrategy;
import com.yowasa.xiuxian.entity.bo.battle.BattleContent;
import com.yowasa.xiuxian.entity.bo.battle.UserBattleContent;
import com.yowasa.xiuxian.util.RandomUtil;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.util.List;

@Component
public class BattleHelper {
    @Autowired
    private BattleStrategyEngine battleStrategyEngine;

    /**
     * 计算防御结果
     *
     * @param user    防御者
     * @param bs      进攻策略
     * @param dmg     造成点原始伤害
     * @param content 战斗内容
     * @return 受伤描述&受伤伤害
     */
    public Pair<String, Integer> duelDefend(UserBattleContent user, UserBattleContent battleUser, BattleStrategy bs, int dmg, BattleContent content) {
        List<DefendStrategy> defendStrategies = battleStrategyEngine.matchDefendStrategy(user, bs, content);
        int calDmg = dmg;
        for (DefendStrategy defendStrategy : defendStrategies) {
            calDmg = defendStrategy.defend(user, battleUser, bs, calDmg, content);
        }
        String name = user.getUserBO().getName();
        if (calDmg == 0) {
            return Pair.of("被" + name + "轻松化解(" + dmg + ")", calDmg);
        }
        String msg;
        if (calDmg == dmg) {
            msg = "对" + name + "造成了" + calDmg + "点伤害";
        } else {
            msg = "对" + name + "造成了" + calDmg + "(" + (calDmg - dmg) + ")" + "点伤害";
        }
        return Pair.of(msg, calDmg);
    }

    //物理伤害计算公式
    public int calAtk(int atk, int def) {
        BigDecimal divide = new BigDecimal(atk).multiply(new BigDecimal(atk)).divide(new BigDecimal(def + atk),0);
        int dmg = divide.intValue();
        dmg = RandomUtil.waveInt(dmg, 50);
        return dmg;
    }
    public int calImm(int atk, int def) {
        BigDecimal divide = new BigDecimal(atk).multiply(new BigDecimal(atk)).divide(new BigDecimal(def + atk),0);
        int dmg = divide.intValue();
        return dmg;
    }

    //术法伤害计算公式
    public int calSpell(int atk, int def) {
        BigDecimal divide = new BigDecimal(atk).multiply(new BigDecimal(atk)).divide(new BigDecimal(def + atk),0);
        int dmg = divide.intValue();
        dmg = RandomUtil.waveInt(dmg, 20);
        return dmg;
    }

    public String buildResultMsg(UserBattleContent first, String method, String defend) {
        return first.getUserBO().getName() + "发动的" + method + defend;
    }

    public void autoAction(BattleStrategy baseBattleStrategy, UserBattleContent first, UserBattleContent second, BattleContent content, int dmg, String atkDesc) {
        Pair<String, Integer> pair = duelDefend(second, first, baseBattleStrategy, dmg, content);
        String msg = buildResultMsg(first, atkDesc, pair.getKey());
        second.getBattleInfo().setChp(second.getBattleInfo().getChp() - pair.getValue());
        content.getMsgLog().add(msg);
    }

    /**
     * 同步结束时的战斗状态
     *
     * @param battle
     */
    public void syncUserState(BattleContent battle) {
        syncUserState(battle.getFirst());
        syncUserState(battle.getSecond());
    }

    private void syncUserState(UserBattleContent user) {
        if (user.getUserBO().getUserConfig().getStudiedSpecialEffect().contains("谷神大法")) {
            user.getUserBO().getUserBattle().setChp(user.getBattleInfo().getHp());
        } else {
            if (user.getBattleInfo().getChp() > user.getUserBO().getUserBattle().getHp()) {
                user.getUserBO().getUserBattle().setChp(user.getUserBO().getUserBattle().getHp());
            }else {
                user.getUserBO().getUserBattle().setChp(user.getBattleInfo().getChp());
            }
        }
        if (user.getBattleInfo().getCmp() > user.getUserBO().getUserBattle().getMp()) {
            user.getUserBO().getUserBattle().setCmp(user.getUserBO().getUserBattle().getMp());
        } else {
            user.getUserBO().getUserBattle().setCmp(user.getBattleInfo().getCmp());
        }

    }

    public int calCostTime(BattleContent battle) {
        int stage = Math.min(battle.getFirst().getUserBO().getStage(), battle.getSecond().getUserBO().getStage());
        int costDay = stage * battle.getTurn() / 10;
        if (costDay < 1) {
            costDay = 1;
        }
        return costDay;
    }
}
